package com.woniuxy.core.service.impl;

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

import com.woniuxy.core.mapper.AllUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class UserSignServiceImpl {
    @Autowired
    private AllUserMapper allUserMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 用户签到
     * @param userId 用户ID
     * @param date 签到日期
     * @return 签到结果（true表示成功，false表示已签到）
     */
    public boolean sign(Long userId, LocalDate date) {
        String key = getSignKey(userId, date);
        int dayOfMonth = date.getDayOfMonth() - 1; // BitMap从0开始计数

        // 签到操作
        boolean result = redisTemplate.execute((RedisConnection connection) -> {
            return connection.setBit(key.getBytes(), dayOfMonth, true);
        });

        // 如果签到成功，则增加金币
        if (!result) {
            allUserMapper.addCoinToUser(userId); // 调用 MyBatis 更新金币
        }

        return result;
    }


    /**
     * 检查用户某天是否已签到
     * @param userId 用户ID
     * @param date 日期
     * @return 是否已签到
     */
    public boolean checkSigned(Long userId, LocalDate date) {
        String key = getSignKey(userId, date);
        int dayOfMonth = date.getDayOfMonth() - 1;

        return redisTemplate.execute((RedisConnection connection) -> {
            return connection.getBit(key.getBytes(), dayOfMonth);
        });
    }

    /**
     * 获取用户某月的签到状态列表
     * @param userId 用户ID
     * @param date 任意一天的日期，用于确定查询哪个月的数据
     * @return 签到状态列表（索引0对应1号，值为true表示已签到）
     */
    public List<Boolean> getMonthSignStatus(Long userId, LocalDate date) {
        YearMonth yearMonth = YearMonth.from(date);
        String key = getSignKey(userId, date); // 使用完整 date 生成 key
        int daysInMonth = yearMonth.lengthOfMonth();

        byte[] bytes = redisTemplate.execute((RedisConnection connection) -> {
            return connection.get(key.getBytes());
        });

        BitSet bitSet = bytes != null ? BitSet.valueOf(bytes) : new BitSet();
        List<Boolean> signStatus = new ArrayList<>(daysInMonth);

        for (int i = 0; i < daysInMonth; i++) {
            signStatus.add(bitSet.get(i));
        }

        // 重新排列签到状态列表
        List<Boolean> reorderedSignStatus = new ArrayList<>(daysInMonth);
        int[] newOrder = {7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 24, 30, 29, 28, 27, 26, 25};
        for (int i = 0; i < daysInMonth; i++) {
            if (i < newOrder.length) {
                reorderedSignStatus.add(signStatus.get(newOrder[i]));
            } else {
                // 如果月份天数不足31天，添加默认值false
                reorderedSignStatus.add(false);
            }
        }

        return reorderedSignStatus;
    }

    /**
     * 获取用户某月已签到的日期列表
     * @param userId 用户ID
     * @param date 任意一天的日期，用于确定查询哪个月的数据
     * @return 已签到的日期列表（如[1, 3, 5]表示1号、3号、5号已签到）
     */
    public List<Integer> getSignedDays(Long userId, LocalDate date) {
        YearMonth yearMonth = YearMonth.from(date);
        String key = getSignKey(userId, date);
        int daysInMonth = yearMonth.lengthOfMonth();

        byte[] bytes = redisTemplate.execute((RedisConnection connection) -> {
            return connection.get(key.getBytes());
        });

        BitSet bitSet = bytes != null ? BitSet.valueOf(bytes) : new BitSet();
        List<Integer> signedDays = new ArrayList<>();

        for (int i = 0; i < daysInMonth; i++) {
            if (bitSet.get(i)) {
                signedDays.add(i + 1); // BitSet索引0对应1号
            }
        }

        return signedDays;
    }

    /**
     * 获取用户连续签到天数
     * @param userId 用户ID
     * @return 连续签到天数
     */
    public int getContinuousSignDays(Long userId) {
        LocalDate now = LocalDate.now();
        String key = getSignKey(userId, now);
        int dayOfMonth = now.getDayOfMonth();

        byte[] bytes = redisTemplate.execute((RedisConnection connection) -> {
            return connection.get(key.getBytes());
        });

        BitSet bitSet = bytes != null ? BitSet.valueOf(bytes) : new BitSet();
        int continuousDays = 0;

        for (int i = dayOfMonth - 1; i >= 0; i--) {
            if (bitSet.get(i)) {
                continuousDays++;
            } else {
                break;
            }
        }

        return continuousDays;
    }

    /**
     * 获取用户总签到次数
     * @param userId 用户ID
     * @param date 任意一天的日期，用于确定查询哪个月的数据
     * @return 总签到次数
     */
    public int getTotalSignCount(Long userId, LocalDate date) {
        String key = getSignKey(userId, date);

        byte[] bytes = redisTemplate.execute((RedisConnection connection) -> {
            return connection.get(key.getBytes());
        });

        BitSet bitSet = bytes != null ? BitSet.valueOf(bytes) : new BitSet();
        return bitSet.cardinality(); // 返回被设置为true的位数
    }

    /**
     * 生成用户签到的Redis键
     * 格式：user:sign:{userId}:{year}-{month}
     */
    public static String getSignKey(Long userId, LocalDate date) {
        return String.format("user:sign:%d:%d-%02d",
                userId,
                date.getYear(),
                date.getMonthValue());
    }
}